<?php

/*
class Application, defines the entry point
Copyright (C) 2011  Petr Čermák

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

require_once 'Component.php';
require_once 'TextBinder.php';

class Application{

    private $globals = array();
    private $topComponent = null;
    private static $application = null;

    protected function init(){}

    public function addGlobal($name, $value){
        $this->globals[$name] = $value;
    }

    public static function getGlobal($name){
        return self::$application->globals[$name];
    }

    /**
     * Sets the top component of the application.
     * @param Component the top component
     */
    public function setTopComponent(Component $component){
        $this->topComponent = $component;
    }

    /**
     * Enables or disables error checking, enabled by default.
     * @param bool value
     */
    public function setErrorCheckingEnabled($enabled){
        Checker::checkBool($enabled);
        $_SESSION['error_checking_enabled'] = $enabled;
    }

    /**
     * Enables or disables session storing, disabled by default.
     * @param bool value
     */
    public function setSessionStoringEnabled($enabled){
        Checker::checkBool($enabled);
        $_SESSION['session_storing_enabled'] = $enabled;
    }

    /**
     * Gets the top component of the application.
     * @return Container
     */
    public static function getTopComponent(){
        return self::$application->topComponent;
    }

    /**
     * Checks if error checking is enabled.
     * @return bool
     */
    public static function isErrorCheckingEnabled(){
        return !isset($_SESSION['error_checking_enabled']) || $_SESSION['error_checking_enabled'] == true;
    }

    /**
     * Checks if session storing is enabled.
     * @return bool
     */
    public static function isSessionStoringEnabled(){
        return isset($_SESSION['session_storing_enabled']) && $_SESSION['session_storing_enabled'] == true;
    }

    /**
     * Runs the application of provided name.
     * @param string application name
     */
    public static function run($className){
        self::initApplication($className);
        if(isset($_GET['action']) || isset($_POST['action']))
            self::runAction();
        else{
            $_SESSION['LAST_URL_PARAMETERS'] = $_GET;
            self::runApplication();
        }
    }

    public static function getValidUrlParameters(){
        if(array_key_exists("action", $_GET))
            return $_SESSION['LAST_URL_PARAMETERS'];
        else return $_GET;
    }

    /*private static function runAction(){
        if($_SERVER['REQUEST_METHOD'] == 'GET')$array = $_GET;
        else $array = $_POST;
        $cn = $array['cn'] - 1;
        $action = $array['action'];
        $comp = self::$application->getTopComponent();
        while($cn >= 0){
            $comp = $comp->getComponent($array["c$cn"]);
            $cn--;
        }
        $comp->$action();
    }*/

    private static function runAction(){
        if($_SERVER['REQUEST_METHOD'] == 'GET')$array = $_GET;
        else $array = $_POST;
        $action = $array['action'];
        $class = $array['class'];
        unset($array['action']);
        unset($array['class']);
        echo(call_user_func_array($class.'::'.$action, $array));
    }

    public static function createActionAddress($class, $action, $arguments){
        $address = $_SERVER['PHP_SELF']."?class=$class&amp;action=$action";
        foreach($arguments as $i => $arg)
            $address .=  "&amp;$i=$arg";
        return $address;
    }
    
    public static function createActionJsObject($class, $action, $arguments){
        $obj = "{class: $class, action: $action";
        foreach($arguments as $i => $arg)
            $obj .=  ", $i: $arg";
        return $obj."}";
    }

    public static function createAddress($params){
        $address = $_SERVER['PHP_SELF'];
        $first = true;
        foreach($params as $key => $value){
            if($first){
                $first = false;
                $address .= "?$key=$value";
            }
            else $address .= "&amp;$key=$value";
        }
        return $address;
    }

    public static function getAddress(){
        return $_SERVER['PHP_SELF'];
    }

    private static function runApplication(){
        $topComponent = self::$application->topComponent;
        $topComponent->processRequest();
    }

    private static function initApplication($className){
        self::includeAll();
        include_once './apps/'.$className.'.php';
        session_start();
        $name = $className."_entryPoint";
        if(!isset($_SESSION[$name])){
            $app = new $className();
            $app->init();
            if(isset($_SESSION['session_storing_enabled']) && $_SESSION['session_storing_enabled'] == true){
                $_SESSION[$name] = $app;
                TextBinder::saveToSession();
            }
        }
        else{
            $app = $_SESSION[$name];
            TextBinder::loadFromSession();
        }
        if(isset($_SESSION['error_checking_enabled']))
            Checker::setEnabled($_SESSION['error_checking_enabled']);
        self::$application = $app;
        $app->topComponent->initialize();
    }

    private static function includeDirectory($dirPath){
        foreach(glob("$dirPath/*.php") as $fileName)require_once($fileName);
    }
    
    private static function includeAll(){
        self::includeDirectory("LooseCOMF");
        self::includeDirectory("controllers");
        self::includeDirectory("models");
    }
    
}
?>
